package com.tbit.uqbike.service.business.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tbit.uqbike.constant.enums.AccountDayStatEnum;
import com.tbit.uqbike.object.pojo.Account;
import com.tbit.uqbike.object.pojo.AccountDayStat;
import com.tbit.uqbike.object.pojo.ArrearsLog;
import com.tbit.uqbike.object.pojo.ArrearsLogSum;
import com.tbit.uqbike.object.pojo.dto.ArrearsLogDTO;
import com.tbit.uqbike.object.pojo.dto.ArrearsLogDownloadDTO;
import com.tbit.uqbike.object.pojo.vo.ArrearsLogDetailSumVO;
import com.tbit.uqbike.object.pojo.vo.ArrearsLogDownLoadVo;
import com.tbit.uqbike.object.pojo.vo.ArrearsLogSumVO;
import com.tbit.common.entity.view.PageResult;
import com.tbit.uqbike.service.business.ArrearsLogService;
import com.tbit.uqbike.webmanager.dao.capital.ArrearsLogDao;
import com.tbit.uqbike.webmanager.dao.core.AccountDao;
import com.tbit.uqbike.webmanager.dao.stat.AccountDayStatDao;
import com.tbit.uqbike.webmanager.util.BeanUtils;
import com.tbit.uqbike.webmanager.util.csv.CsvExportUtils;
import com.tbit.uqbike.webmanager.util.csv.entity.ExportHandler;
import com.tbit.utils.DateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;

/**
 * @Author:BUGTian
 * @DATE: 2022/11/14
 */
@Service
public class ArrearsLogServiceImpl implements ArrearsLogService {

    @Autowired
    private AccountDayStatDao accountDayStatDao;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private ArrearsLogDao arrearsLogDao;
    @Autowired
    private CsvExportUtils csvExportUtils;

    @Override
    public ArrearsLogSumVO sumArrears(Integer brandId, String adAccountIds, Date startTime, Date endTime) {
        //按区域汇总数据
        List<ArrearsLogSum> arrearsLogSumList = new ArrayList<>();
        List<Integer> accountIds = new LinkedList<>();
        for (String s : adAccountIds.split(",")) {
            accountIds.add(Integer.parseInt(s));
        }
        Date date = accountDayStatDao.selectLatelyDataTime(accountIds);
        //汇总数据
        ArrearsLogSum sum = new ArrearsLogSum(brandId, null, null, date, 0D, 0L, 0D, 0L, 0D, 0L, 0D, 0L, 0D, 0L);
        List<Account> accountList = accountDao.getByAccountIds(accountIds);
        //统计本期欠款数据
        Map<String, AccountDayStat> map = accountDayStatDao.sumArrears(brandId, accountIds,
                DateTimeUtil.parseDataDate(startTime),
                DateTimeUtil.parseDataDate(endTime),
                ListUtil.toList(
                        AccountDayStatEnum.AMOUNT_OWED.getDataType(),
                        AccountDayStatEnum.RECHARGE_AMOUNT_OF_ARREARS.getDataType(),
                        AccountDayStatEnum.SUPPLEMENTARY_VIRTUAL_AMOUNT_OF_ARREARS.getDataType()));
        //期初
        Map<String, AccountDayStat> startMap = accountDayStatDao.sumArrears(brandId, accountIds,
                DateTimeUtil.parseDataDate(DateUtil.offsetDay(startTime, -1)),
                DateTimeUtil.parseDataDate(DateUtil.offsetDay(startTime, -1)),
                ListUtil.toList(AccountDayStatEnum.DEBT_AT_THE_BEGINNING_AND_END_OF_THE_PERIOD.getDataType()));
        //期末
        Map<String, AccountDayStat> endMap = accountDayStatDao.sumArrears(brandId, accountIds,
                DateTimeUtil.parseDataDate(endTime),
                DateTimeUtil.parseDataDate(endTime),
                ListUtil.toList(AccountDayStatEnum.DEBT_AT_THE_BEGINNING_AND_END_OF_THE_PERIOD.getDataType()));
        for (Account account : accountList) {
            Integer accountId = account.getAccountId();
            ArrearsLogSum data = new ArrearsLogSum()
                    .setAreaName(account.getName())
                    .setAccountId(accountId)
                    .setBrandId(brandId)
                    .setDataTime(date)
                    .setArrearsMoney(getMoney(map, AccountDayStatEnum.AMOUNT_OWED.getDataType(), accountId))
                    .setArrearsCount(getCount(map, AccountDayStatEnum.AMOUNT_OWED.getDataType(), accountId))
                    .setArrearsPaymentMoney(getMoney(map, AccountDayStatEnum.RECHARGE_AMOUNT_OF_ARREARS.getDataType(), accountId))
                    .setArrearsPaymentCount(getCount(map, AccountDayStatEnum.RECHARGE_AMOUNT_OF_ARREARS.getDataType(), accountId))
                    .setArrearsPaymentVirtualMoney(getMoney(map, AccountDayStatEnum.SUPPLEMENTARY_VIRTUAL_AMOUNT_OF_ARREARS.getDataType(), accountId))
                    .setArrearsPaymentVirtualCount(getCount(map, AccountDayStatEnum.SUPPLEMENTARY_VIRTUAL_AMOUNT_OF_ARREARS.getDataType(), accountId))
                    .setStartArrearsMoney(getMoney(startMap, AccountDayStatEnum.DEBT_AT_THE_BEGINNING_AND_END_OF_THE_PERIOD.getDataType(), accountId))
                    .setStartArrearsCount(getCount(startMap, AccountDayStatEnum.DEBT_AT_THE_BEGINNING_AND_END_OF_THE_PERIOD.getDataType(), accountId))
                    .setEndArrearsMoney(getMoney(endMap, AccountDayStatEnum.DEBT_AT_THE_BEGINNING_AND_END_OF_THE_PERIOD.getDataType(), accountId))
                    .setEndArrearsCount(getCount(endMap, AccountDayStatEnum.DEBT_AT_THE_BEGINNING_AND_END_OF_THE_PERIOD.getDataType(), accountId));
            arrearsLogSumList.add(data);
            sum.setArrearsMoney(NumberUtil.add(sum.getArrearsMoney(), data.getArrearsMoney()))
                    .setArrearsCount(sum.getArrearsCount() + data.getArrearsCount())
                    .setArrearsPaymentMoney(NumberUtil.add(sum.getArrearsPaymentMoney(), data.getArrearsPaymentMoney()))
                    .setArrearsPaymentCount(sum.getArrearsPaymentCount() + data.getArrearsPaymentCount())
                    .setArrearsPaymentVirtualMoney(NumberUtil.add(sum.getArrearsPaymentVirtualMoney(), data.getArrearsPaymentVirtualMoney()))
                    .setArrearsPaymentVirtualCount(sum.getArrearsPaymentVirtualCount() + data.getArrearsPaymentVirtualCount())
                    .setStartArrearsMoney(NumberUtil.add(sum.getStartArrearsMoney(), data.getStartArrearsMoney()))
                    .setStartArrearsCount(sum.getStartArrearsCount() + data.getStartArrearsCount())
                    .setEndArrearsMoney(NumberUtil.add(sum.getEndArrearsMoney(), data.getEndArrearsMoney()))
                    .setEndArrearsCount(sum.getEndArrearsCount() + data.getEndArrearsCount());
        }
        return new ArrearsLogSumVO(sum, arrearsLogSumList);
    }

    @Override
    public PageResult<ArrearsLog> arrearsLogPage(ArrearsLogDTO arrearsLogDTO) {
        QueryWrapper<ArrearsLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("brandId", arrearsLogDTO.getBrandId())
                .in("accountId", arrearsLogDTO.getAccountIdList())
                .between("changeTime", arrearsLogDTO.getStartTime().getTime(), arrearsLogDTO.getEndTime().getTime())
                .orderBy(true, false, "changeTime");
        splicingQueryWrapper(queryWrapper, "dataType", arrearsLogDTO.getDataType());
        splicingQueryWrapper(queryWrapper, "makeUpType", arrearsLogDTO.getMakeUpType());
        splicingQueryWrapper(queryWrapper, "userPhone", arrearsLogDTO.getUserPhone());
        splicingQueryWrapper(queryWrapper, "businessNO", arrearsLogDTO.getBusinessNO());
        Integer page = arrearsLogDTO.getPage();
        Integer size = arrearsLogDTO.getSize();

        PageInfo<ArrearsLog> pageInfo = PageHelper.startPage(page, size).doSelectPageInfo(() -> arrearsLogDao.selectList(queryWrapper));
        return new PageResult<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());
    }

    @Override
    public ArrearsLogDetailSumVO arrearsLogDetailSum(ArrearsLogDTO arrearsLogDTO) {
        arrearsLogDTO.setSTime(arrearsLogDTO.getStartTime().getTime());
        arrearsLogDTO.setETime(arrearsLogDTO.getEndTime().getTime());
        return arrearsLogDao.querySum(arrearsLogDTO);
    }

    @Override
    public String download(ArrearsLogDownloadDTO downloadDTO) {
        downloadDTO.setFileName("欠款统计账单");


        File tempFile = csvExportUtils.getTempFile();
        try {
            File file = download(downloadDTO, tempFile);
            String uploadFileName = UUID.randomUUID().toString().replaceAll("-", "");
            return csvExportUtils.uploadZip(tempFile, uploadFileName, file);
        } finally {
            FileUtil.del(tempFile);
        }
    }

    public File download(ArrearsLogDownloadDTO downloadDTO, File tempFile) {
        ExportHandler exportHandler = baseEntity -> {
            ArrearsLogDownloadDTO dto = BeanUtils.copyProperties(downloadDTO, ArrearsLogDownloadDTO.class);
            dto.setStartTime(baseEntity.getStartTime());
            dto.setEndTime(baseEntity.getEndTime());
            List<Integer> accountIdList = new LinkedList<>();
            for (String s : dto.getAccountIds().split(",")) {
                accountIdList.add(Integer.parseInt(s));
            }
            List<ArrearsLogDownLoadVo> list = arrearsLogDao.selectArrearsLogDownLoadVoList(dto.getBrandId(), accountIdList,
                    dto.getStartTime().getTime(), dto.getEndTime().getTime(), dto.getDataType(), dto.getMakeUpType(), dto.getUserPhone(), dto.getBusinessNO());
            return list;
        };
        Date startTime = downloadDTO.getStartTime();
        Date endTime = downloadDTO.getEndTime();
        return csvExportUtils.export(exportHandler, ArrearsLogDownLoadVo.class, startTime, endTime, tempFile, downloadDTO.getFileName());
    }

    /**
     * 获取金额
     *
     * @param map
     * @param type
     * @param accountId
     * @return
     */
    public Double getMoney(Map<String, AccountDayStat> map, Integer type, Integer accountId) {
        AccountDayStat accountDayStat = map.get(accountId + "_" + type);
        return accountDayStat == null ? 0D : (double) accountDayStat.getSumTotal() / 100D;
    }

    /**
     * 获取数量
     *
     * @param map
     * @param type
     * @param accountId
     * @return
     */
    public Long getCount(Map<String, AccountDayStat> map, Integer type, Integer accountId) {
        AccountDayStat accountDayStat = map.get(accountId + "_" + type);
        return accountDayStat == null ? 0 : accountDayStat.getCntTotal();
    }

    /**
     * 动态拼接查询条件
     *
     * @param queryWrapper
     * @param column
     * @param param
     */
    public void splicingQueryWrapper(QueryWrapper<ArrearsLog> queryWrapper, String column, Object param) {
        if (param != null) {
            if (param instanceof String && "".equals(param)) {
                return;
            }
            queryWrapper.eq(column, param);
        }
    }

}
